local skynet = require "skynet"
local tabletool = require "tabletool"
local cardtool = require "dncardtool"
local base = require "base"
local filelog = require "filelog"
local redisdao = require "redisdao"
local json = require "cjson"
json.encode_sparse_array(true,1,1)

require "pubenum"
require "dnenum"

local server = nil
local robot_bet_info = {}
local tableRobotHelper = {}

local function get_robotfirst()
	local dnnodeconf = nil
	local robot_first = 1
	local result, data = redisdao.query_data(".gmmqredis", "get", "dnnode_conf")
    if result and data then
        dnnodeconf = json.decode(data)
        robot_first = tabletool.deepcopy(dnnodeconf.robot_first)
    end
    return robot_first
end

local function get_dn_robot_match_conf()
    local dnnodeconf = nil
    local robot_match_conf = nil
    local result, data = redisdao.query_data(".gmmqredis", "get", "dnnode_conf")
    if result and data then
        dnnodeconf = json.decode(data)
        robot_match_conf = tabletool.deepcopy(dnnodeconf.robot_match_conf)
    end
    if not robot_match_conf then
        return nil
    else
        return robot_match_conf
    end
end

local function valueswap(sourc, a, b)
	sourc[a], sourc[b] = sourc[b], sourc[a]
end

local function allrange(sourc, start, length, result)
	if start == length - 1 then
		local cpsourc = tabletool.deepcopy(sourc)
		table.insert(result, cpsourc)
	else
		for i = start, length -1  do
			valueswap(sourc, start, i)
			allrange(sourc, start + 1, length, result)
			valueswap(sourc, start, i)
		end
	end
end

function tableRobotHelper.init(service)
	if server == nil then
		server = service
	end
end

function tableRobotHelper.gettablewininfo()
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local tablelogic = server:get_logicbyname("tablelogic")
	robot_bet_info = {}
	local gamename = tablelogic.get_gamename()
	local status, result = skynet.pcall(skynet.call, ".slotmgr", "lua", "gettablewininfo", gamename)
	local table_robot_num, robot_rids = tableRobotHelper.get_tablerobotnum()
	local player_num, player_rids = tableRobotHelper.get_realplayernum()
	if table_robot_num == 0 then return end
	table_data.index_cards_asspools = {}
	local all_kinds = tableRobotHelper.gen_all_kinds()
	---filelog.sys_error("-------table_data.deal_cards_temp-----", table_data.deal_cards_temp)
	local sorted_cards = tableRobotHelper.sort_cardstype()
	---filelog.sys_error("--------sorted_cards------", result, sorted_cards)
	robot_bet_info.result = result
	if result == 1 then
		----这局系统随机输钱或赢钱
		----local robot_first = get_robotfirst()
		for i, sorted_cardobj in ipairs(sorted_cards) do
			local temp = base.get_random(1,10)
			if temp <= 6 and #robot_rids > 0 then
				for k, rid in ipairs(robot_rids) do
					if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
						table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
						sorted_cardobj.is_as = true
						table.remove(robot_rids, k)
					end
				end
			else
				if #player_rids > 0 then
					for k, rid in ipairs(player_rids) do
						if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
							table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
							---table.remove(sorted_cards, i)
							sorted_cardobj.is_as = true
							table.remove(player_rids, k)
						end
					end
				else
					for k, rid in ipairs(robot_rids) do
						if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
							table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
							---table.remove(sorted_cards, i)
							sorted_cardobj.is_as = true
							table.remove(robot_rids, k)
						end
					end
				end
			end
		end
	elseif result == 2 then
		---这局系统要赢钱,机器人先分牌
		for i, sorted_cardobj in ipairs(sorted_cards) do
			for k, rid in ipairs(robot_rids) do
				if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
					table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
					---table.remove(sorted_cards, i)
					sorted_cardobj.is_as = true
					table.remove(robot_rids, k)
				end
			end
		end
		for i, sorted_cardobj in ipairs(sorted_cards) do
			for k, rid in ipairs(player_rids) do
				if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
					table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
					--table.remove(sorted_cards, i)
					sorted_cardobj.is_as = true
					table.remove(player_rids, k)
				end
			end
		end
	elseif result == 3 then
		---这局系统要输钱,玩家先分牌
		for i, sorted_cardobj in ipairs(sorted_cards) do
			for k, rid in ipairs(player_rids) do
				if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
					table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
					--table.remove(sorted_cards, i)
					sorted_cardobj.is_as = true
					table.remove(player_rids, k)
				end
			end
		end
		for i, sorted_cardobj in ipairs(sorted_cards) do
			for k, rid in ipairs(robot_rids) do
				if table_data.index_cards_asspools[rid] == nil and sorted_cardobj.is_as == false then
					table_data.index_cards_asspools[rid] = sorted_cardobj.cards_index
					--table.remove(sorted_cards, i)
					sorted_cardobj.is_as = true
					table.remove(robot_rids, k)
				end
			end
		end
	end
	---filelog.sys_error("----------overcome--------", table_data.index_cards_asspools)
	if not tableRobotHelper.check_cards_asspools() then
		table_data.index_cards_asspools = {}
	end 
end

function tableRobotHelper.check_cards_asspools()
	local table_data = server.table_data
	local table_robot_num, robot_rids = tableRobotHelper.get_tablerobotnum()
	local player_num, player_rids = tableRobotHelper.get_realplayernum()
	local temp_num = 0
	for index, value in pairs(table_data.index_cards_asspools) do
		temp_num = temp_num + 1
	end
	if temp_num ~= 0 and temp_num == table_robot_num + player_num then
		return true
	else
		return false
	end
end

function tableRobotHelper.gen_all_kinds()
	local table_data = server.table_data
	local seatlogic = server:get_logicbyname("seatlogic")
	local basekinds = {}
	for index, seat in ipairs(table_data.seats) do
		if seatlogic.is_ingame(seat) then
			table.insert(basekinds, seat.index)
		end
	end
	local resultkinds = {}
	allrange(basekinds, 1, #basekinds+1, resultkinds)
	return resultkinds
end

function tableRobotHelper.sort_cardstype()
	-- body
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return {} end
	local cards_temp = {}
	for index, cards in pairs(table_data.deal_cards_temp) do
		local seat_temp = {
			cards = tabletool.deepcopy(cards),
			card_type = 0,
			final_cards = tabletool.deepcopy(cards),
		}
		cardtool.analysis_card_type(seat_temp, seat_temp.cards, table_data.conf.is_open_flush)
		table.insert(cards_temp, { cards_index = index, cards = tabletool.deepcopy(cards), card_type = seat_temp.card_type, is_as = false })
	end
	local function compcards(first, second)
		local first_temp = {
			cards = tabletool.deepcopy(first.cards),
			card_type = 0,
			final_cards = tabletool.deepcopy(first.cards),
		}
		cardtool.analysis_card_type(first_temp, first_temp.cards, table_data.conf.is_open_flush)
		local second_temp = {
			cards = tabletool.deepcopy(second.cards),
			card_type = 0,
			final_cards = tabletool.deepcopy(second.cards),
		}
		cardtool.analysis_card_type(second_temp, second_temp.cards, table_data.conf.is_open_flush)
		local flag = cardtool.compare_card_type(first_temp, second_temp)
		if flag == true then
			return true
		else
			return false
		end
	end

	table.sort(cards_temp, function(first, second)
		if first.card_type > second.card_type then 
			return true
		elseif first.card_type == first.card_type then
			return compcards(first, second)
		else
			return false
		end
	end)
	return cards_temp
end


function tableRobotHelper.gen_all_handcards_balance(allhandcards)
	local table_data = server.table_data
	local overcome_balance = {}
	local normal_balance = {}
	local win_balance = {}
	local lose_balance = {}
	local must_lost_balance = {}
	local system_overcome = 0
	for k, playerscards in ipairs(allhandcards) do
		system_overcome = 0
		local temp_banker_index = playerscards[1]
		local temp_zhuang_seat = table_data.seats[temp_banker_index]
		local zhuang_cards = table_data.deal_cards_temp[playerscards[1]]
		local banker_xiazhu_times = 4
		local win_tablerobot = 0
		local lose_tablerobot = 0
		local zhuang_temp_seat = {
			cards = tabletool.deepcopy(zhuang_cards),
			card_type = 0,
			final_cards = tabletool.deepcopy(zhuang_cards),
		}
		cardtool.analysis_card_type(zhuang_temp_seat, zhuang_temp_seat.cards, table_data.conf.is_open_flush)
		for index, cardsindex in ipairs(playerscards) do
			if cardsindex ~= temp_banker_index then
				---filelog.sys_error("-------index--------", cardsindex)
				local seat_cards = table_data.deal_cards_temp[cardsindex]
				local seat_temp = {
					cards = tabletool.deepcopy(seat_cards),
					card_type = 0,
					final_cards = tabletool.deepcopy(seat_cards),
				}
				cardtool.analysis_card_type(seat_temp, seat_temp.cards, table_data.conf.is_open_flush)
				local flag = cardtool.compare_card_type(zhuang_temp_seat, seat_temp)
				if flag == true then
					----庄家大于闲家
					local seat = table_data.seats[cardsindex]
					if temp_zhuang_seat.is_robot == true then
						local dealnum = table_data.conf.score_diamond * banker_xiazhu_times * 3 * DNORTimesType[tostring(zhuang_temp_seat.card_type)]
						win_tablerobot = win_tablerobot + dealnum
					end
					if seat.is_robot == true then
						local dealnum = table_data.conf.score_diamond * banker_xiazhu_times * 3 * DNORTimesType[tostring(zhuang_temp_seat.card_type)]
						lose_tablerobot = lose_tablerobot - dealnum
					end
				else
					local seat = table_data.seats[cardsindex]
					if temp_zhuang_seat.is_robot == true then
						local dealnum = table_data.conf.score_diamond * banker_xiazhu_times * 3 * DNORTimesType[tostring(seat_temp.card_type)]
						lose_tablerobot = lose_tablerobot - dealnum
					end
					if seat.is_robot == true then
						local dealnum = table_data.conf.score_diamond * banker_xiazhu_times * 3 * DNORTimesType[tostring(seat_temp.card_type)]
						win_tablerobot = win_tablerobot + dealnum
					end
				end
			end
		end
		system_overcome = win_tablerobot - lose_tablerobot
		if system_overcome < - temp_zhuang_seat.diamond then
			table.insert(must_lost_balance, { index = k, system_overcome = system_overcome })
		elseif system_overcome > - temp_zhuang_seat.diamond and system_overcome < 0 then
			table.insert(lose_balance, { index = k, system_overcome = system_overcome })
			table.insert(normal_balance, { index = k, system_overcome = system_overcome })
		elseif system_overcome >= 0 then
			table.insert(win_balance, { index = k, system_overcome = system_overcome })
			table.insert(normal_balance, { index = k, system_overcome = system_overcome })
		end
	end
	return normal_balance, win_balance, lose_balance
end

function tableRobotHelper.killallrobots()

end

function tableRobotHelper.get_tablerobotnum()
	local table_data = server.table_data
	local seatlogic = server:get_logicbyname("seatlogic")
	local table_robot_num = 0
	local robot_rids = {}
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true and seatlogic.is_ingame(seat) then 
			table_robot_num = table_robot_num + 1
			table.insert(robot_rids, seat.rid)
		end
	end
	return table_robot_num, robot_rids
end

function tableRobotHelper.get_realplayernum()
	local table_data = server.table_data
	local seatlogic = server:get_logicbyname("seatlogic")
	local real_player_num = 0
	local player_rids = {}
	for index, seat in pairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == false and seatlogic.is_ingame(seat) then 
			real_player_num = real_player_num + 1 
			table.insert(player_rids, seat.rid)
		end
	end
	local new_player_rids = {}
	if #player_rids > 1 then
		for i = 1, #player_rids do
			local temp_index = base.get_random(1, #player_rids)
			if player_rids[temp_index] then
				table.insert(new_player_rids, table.remove(player_rids, temp_index))
			end
		end
		return real_player_num, new_player_rids
	else
		return real_player_num, player_rids
	end
end

function tableRobotHelper.getalltablerobots()
	local table_data = server.table_data
	local tablerobots = {}
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true then table.insert(tablerobots, seat.rid) end
	end
	return tablerobots
end

function tableRobotHelper.adjustrobots()
	local table_data = server.table_data
	local tablelogic = server:get_logicbyname("tablelogic")
	local real_player_num = tableRobotHelper.get_realplayernum()
	local robot_num = tableRobotHelper.get_tablerobotnum()
end

function tableRobotHelper.send_notice_torobots(rids, msgname, message, retcode, retstr)
	skynet.send(".robotmgr", "lua", msgname, rids, message, retcode, retstr)
end

function tableRobotHelper.notice_robot_ready()
	local table_data = server.table_data
	local is_open = tableRobotHelper.check_open_robot()
	if not is_open then return end
	local robot_num, robot_rids = 0, {}
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true then 
			robot_num = robot_num + 1
			table.insert(robot_rids, seat.rid)
		end
	end
	if robot_num > 0 then
		skynet.send(".robotmgr", "lua", "doready", robot_rids)
	end
end

function tableRobotHelper.notice_robot_qiangzhuang()
	---filelog.sys_error("--------tableRobotHelper.notice_robot_qiangzhuang-----")
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local tablelogic = server:get_logicbyname("tablelogic")
	local gamename = tablelogic.get_gamename()
	local robot_num, robot_rids = 0, {}
	for index, seat in ipairs(table_data.seats) do
		----filelog.sys_error("-----------index,seat.rid----",index, seat.rid, seat.is_robot, seat.playerinfo.level)
		if seat.rid ~= 0 and seat.is_robot == true and seat.state ~= DNSeatState.SEAT_STATE_WAIT_NEXT_GAME then
			robot_num = robot_num + 1
			table.insert(robot_rids, seat.rid)
		end
	end
	if robot_num == 0 then return end
	for index, robot_rid in ipairs(robot_rids) do
		if robot_bet_info.result == 2 then
			local callbanker_times = 4
			if base.get_random(1,10) < 6 then
				callbanker_times = 0
			end
			skynet.send(".robotmgr", "lua", "callbanker", robot_rid, callbanker_times)
		elseif robot_bet_info.result == 3 then
			local callbanker_times = skynet.call(".slotmgr", "lua", "get_callbanker_times", gamename, false)
			skynet.send(".robotmgr", "lua", "callbanker", robot_rid, callbanker_times)
		elseif robot_bet_info.result == 1 then
			local robot_seat = tablelogic.get_seat_by_rid(table_data, robot_rid)
			if robot_seat then
			----local cards_index = table_data.index_cards_asspools[robot_rid]
				local cards_deal_temp = table_data.deal_cards_temp[robot_seat.index]
				if cards_index and cards_deal_temp then
					local temp_seat = {
						cards = tabletool.deepcopy(cards_deal_temp),
						card_type = 0,
						final_cards = tabletool.deepcopy(cards_deal_temp),
					}
					cardtool.analysis_card_type(temp_seat, temp_seat.cards, table_data.conf.is_open_flush)
					if temp_seat.card_type > DNCardType.CARD_TYPE_MEINIU then
						local callbanker_times = skynet.call(".slotmgr", "lua", "get_callbanker_times", gamename, true)
						skynet.send(".robotmgr", "lua", "callbanker", robot_rid, callbanker_times)
					else
						local callbanker_times = skynet.call(".slotmgr", "lua", "get_callbanker_times", gamename, false)
						skynet.send(".robotmgr", "lua", "callbanker", robot_rid, callbanker_times)
					end
				else
					local callbanker_times = skynet.call(".slotmgr", "lua", "get_callbanker_times", gamename, false)
					skynet.send(".robotmgr", "lua", "callbanker", robot_rid, callbanker_times)
				end
			end
		end
	end
end

function tableRobotHelper.notice_robot_xiazhu()
	---filelog.sys_error("--------tableRobotHelper.notice_robot_xiazhu-----")
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local tablelogic = server:get_logicbyname("tablelogic")
	local gamename = tablelogic.get_gamename()
	local robot_num, robot_rids = 0, {}
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true and 
			seat.state ~= DNSeatState.SEAT_STATE_WAIT_NEXT_GAME and seat.index ~= table_data.banker_seat_index then
			robot_num = robot_num + 1
			table.insert(robot_rids, seat.rid)
		end
	end
	if robot_num == 0 then return end
	for _, robot_rid in ipairs(robot_rids) do
		local cards_index = table_data.index_cards_asspools[robot_rid]
		local cards_deal_temp = table_data.deal_cards_temp[cards_index]
		if cards_index and cards_deal_temp then
			local temp_seat = {
				cards = tabletool.deepcopy(cards_deal_temp),
				card_type = 0,
				final_cards = tabletool.deepcopy(cards_deal_temp),
			}
			cardtool.analysis_card_type(temp_seat, temp_seat.cards, table_data.conf.is_open_flush)
			if temp_seat.card_type > DNCardType.CARD_TYPE_MEINIU then
				local xiazhu_times = skynet.call(".slotmgr", "lua", "get_xiazhu_times", gamename, true)
				if robot_bet_info.result == 2 then
					xiazhu_times = 3
				end
				skynet.send(".robotmgr", "lua", "dobets", robot_rid, xiazhu_times)
			else
				local xiazhu_times = skynet.call(".slotmgr", "lua", "get_xiazhu_times", gamename, false)
				if robot_bet_info.result == 2 then
					xiazhu_times = 3
				end
				skynet.send(".robotmgr", "lua", "dobets", robot_rid, xiazhu_times)
			end
		else
			local xiazhu_times = skynet.call(".slotmgr", "lua", "get_xiazhu_times", gamename, false)
			if robot_bet_info.result == 2 then
				xiazhu_times = 3
			end
			skynet.send(".robotmgr", "lua", "dobets", robot_rid, xiazhu_times)
		end
	end
end

function tableRobotHelper.balance_notice_robots(balanceinfo, comments)
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local tablelogic = server:get_logicbyname("tablelogic")
	local gamename = tablelogic.get_gamename()
	local robot_num, robot_rids = 0, {}
	local robot_balanceinfos = {}
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true and seat.state ~= DNSeatState.SEAT_STATE_WAIT_NEXT_GAME then
			if balanceinfo[seat.rid] then
				if robot_balanceinfos[seat.rid] == nil then
					robot_balanceinfos[seat.rid] = tabletool.deepcopy(balanceinfo[seat.rid])
				end
			end
		end
	end
	skynet.send(".robotmgr", "lua", "update_balance", robot_balanceinfos, comments, table_data.conf.enter_diamond)
end

function tableRobotHelper.notice_robot_kaipai()
	local table_data = server.table_data
	local tablelogic = server:get_logicbyname("tablelogic")
	local robot_rids, robot_num = {}, 0
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true and seat.state ~= DNSeatState.SEAT_STATE_WAIT_NEXT_GAME then
			robot_num = robot_num + 1
			table.insert(robot_rids, seat.rid)
		end
	end
	skynet.send(".robotmgr", "lua", "kaipai", robot_rids)
end

function tableRobotHelper.check_robot_diamond()
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local tablelogic = server:get_logicbyname("tablelogic")
	for index, seat in ipairs(table_data.seats) do
		if seat.rid ~= 0 and seat.is_robot == true and seat.playerinfo.level == 99 then
			---robot_num = robot_num + 1
			---table.insert(robot_rids, seat.rid)
			if seat.diamond < table_data.conf.enter_diamond or seat.is_delay_leave == true then
				tablelogic.passive_standuptable(table_data, nil, seat, DNEStandupReason.STANDUP_REASON_READYTIMEOUT_STANDUP)
			end
		end
	end
end

function tableRobotHelper.check_open_robot()
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local status, robotstate = skynet.pcall(skynet.call, ".robotmgr", "lua", "get_game_robot_state")
    ---filelog.sys_error("------status, robotstate------", status, robotstate)
    if robotstate == false then return false end
    local is_open_state = false
    local robot_match_conf = get_dn_robot_match_conf()
    if not robot_match_conf then return is_open_state end
    local state, all_match_players = skynet.pcall(skynet.call, ".router", "lua", "get_matchroom_count")
    if not state or not all_match_players then return is_open_state end
    if not table_data or not table_data.conf or not table_data.conf.match_type then return is_open_state end
    local now_player = all_match_players[table_data.conf.match_type]
    if not now_player or not now_player.total_player then return is_open_state end
    local temp_robot_match = robot_match_conf[table_data.conf.match_type]
    if not temp_robot_match then return is_open_state end
    if temp_robot_match.is_open == false then return is_open_state end
    if temp_robot_match.is_open == true and now_player.total_player >= temp_robot_match.min_player_num then
    	is_open_state = true
    end
    return is_open_state
end

function tableRobotHelper.check_robot_num()
	local table_data = server.table_data
	if not table_data.conf or table_data.is_deleting == true then return end
	local is_open = tableRobotHelper.check_open_robot()
	if not is_open then return end
	local tablelogic = server:get_logicbyname("tablelogic")
	local robot_num = 0
	for index, seat in ipairs(table_data.seats) do
		if seat.rid > 0 and seat.playerinfo and seat.playerinfo.level == 99 then
			robot_num = robot_num + 1
		end
	end
	local player_num, player_rids = tableRobotHelper.get_realplayernum()
	if robot_num > 0 then 
		return 
	else
		if player_num == 0 then
			return 
		else
			if player_num < 7 then
				skynet.send(".robotmgr", "lua", "add_robot_to_table",skynet.self(), table_data.conf.table_index, 1, table_data.conf.enter_diamond)
			-- elseif player_num == 7 then
			-- 	local kick_index = base.get_random(1,7)
			-- 	local kick_seat = table_data.seats[kick_index]
			-- 	if kick_seat then
			-- 		tablelogic.passive_standuptable(table_data, nil, kick_seat, DNEStandupReason.STANDUP_REASON_READYTIMEOUT_STANDUP)
			-- 		skynet.send(".robotmgr", "lua", "add_robot_to_table",skynet.self(), table_data.conf.table_index, 1, table_data.conf.enter_diamond)
			-- 	end
			end
		end
	end
end

return tableRobotHelper